package cn.tedu.charging.order.service.impl;

import cn.tedu.charging.common.constant.AmqpComponentConst;
import cn.tedu.charging.common.constant.MqttDestinationConst;
import cn.tedu.charging.common.pojo.message.ChargingStartCheckMessage;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.common.pojo.param.OrderAddParam;
import cn.tedu.charging.common.protocol.JsonResult;
import cn.tedu.charging.common.utils.CronUtil;
import cn.tedu.charging.common.utils.SnowflakeIdGenerator;
import cn.tedu.charging.common.utils.XxlJobTaskUtil;
import cn.tedu.charging.order.client.DeviceClient;
import cn.tedu.charging.order.client.UserClient;
import cn.tedu.charging.order.producer.AmqpProducer;
import cn.tedu.charging.order.producer.MqttProducer;
import cn.tedu.charging.order.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private DeviceClient deviceClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private MqttProducer mqttProducer;
    @Autowired
    private AmqpProducer amqpProducer;
    /*
    datacenterId: 数据中心id 0~31
    machineId: 机器id 0~31
     */
    SnowflakeIdGenerator generator=new SnowflakeIdGenerator(1,1);
    @Override
    public String createOrder(OrderAddParam param) {
        //1.检查设备信息 是否允许充电开始
        checkGunAvailable(param.getGunId());
        //2.检查车辆车主充电枪是否匹配
        checkUserAvailable(param.getUserId(),param.getGunId());
        //3.上述检查结构都ok,生成订单编号
        String billId=generator.nextId()+"";
        //4.给设备发送命令开始检查充电
        sendStartCheckCommand(param,billId);
        //5.发送一个延迟消息 检查设备无响应
        sendDelayCheck(param,billId);
        //6.订单开始充电之后,有可能最终没有处理充电过程异常导致突然结束
        //XxlJobTaskUtil.createJobTask(CronUtil.delayCron(1000*60*2),"order-executor",billId);
        //7.当前业务流程走完,订单最终结果什么样接口无法知道
        //但是有一点可以肯定 这个枪肯定是被用户占用了 修改枪状态
        return billId;
    }

    private void sendDelayCheck(OrderAddParam param, String billId) {
        //1.组织一个延迟消息 对象DelayCheckMessage
        DelayCheckMessage message=new DelayCheckMessage();
        message.setOrderNo(billId);
        message.setUserId(param.getUserId());
        message.setGunId(param.getGunId());
        message.setPileId(param.getPileId());
        //2.发送延迟 ,定义延迟时间 1分钟 60秒 底层毫秒
        amqpProducer.send(AmqpComponentConst.DELAY_BILL_EX,"",message,1000*60l);
    }

    private void sendStartCheckCommand(OrderAddParam param, String billId) {
        //1.组织一个消息对象
        ChargingStartCheckMessage message=new ChargingStartCheckMessage();
        message.setOrderNo(billId);
        message.setUserId(param.getUserId());
        message.setGunId(param.getGunId());
        //2.发送 qos=1 retained=true 发送到目标充电桩绑定主题pileId
        String topic= MqttDestinationConst.START_GUN_CHECK_PREFIX+param.getPileId();
        mqttProducer.send(topic,message);
    }

    private void checkUserAvailable(Integer userId, Integer gunId) {
        log.info("检查用户{}是否允许充电到枪{}",userId,gunId);
        JsonResult<Boolean> jsonResult = userClient.checkUserCharge(userId, gunId);
        if (!jsonResult.getData()){
            log.error("检查用户失败,userId={},gunId={},jsonResult={}",userId,gunId,jsonResult);
            throw new RuntimeException("用户不允许充电");
        }
    }

    private void checkGunAvailable(Integer gunId) {
        log.info("检查枪是否可用,gunId={}",gunId);
        JsonResult<Boolean> jsonResult = deviceClient.checkGun(gunId);
        if (!jsonResult.getData()){
            log.error("检查枪失败,gunId={}",gunId);
            //异常抛出
            throw new RuntimeException("枪不可用");
        }
    }
}
